package com.atlin.project.utils.file;

import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author atlin
 * @description minio 文件服务工具类
 * @createDate 2025/1/3 12:28
 */
@Slf4j
@Component
public class MinioUtil {

    @Value("${minio.bucket-name}")
    private String bucketName;

    @Resource
    private MinioClient minioClient;


    @PostConstruct
    public void minioUtilInitCheck() {
        try {
            if (!bucketExists()) {
                makeBucket();
            }
            log.info("[MinIo文件服务] 初始化成功 {}", bucketName);
        } catch (Exception e) {
            log.error("[MinIo文件服务] minioUtilInitCheck error", e);
//            throw new RuntimeException(e);
        }
    }

    public String putObject(String fileName, MultipartFile multipartFile) {
        try (InputStream inputStream = multipartFile.getInputStream()) {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(inputStream, inputStream.available(), -1)
                    .contentType(multipartFile.getContentType())
                    .build();
            minioClient.putObject(putObjectArgs);
            return getPreUrl(fileName);
        } catch (Exception e) {
            log.error("[MinIo文件服务异常] ", e);
            delObject(fileName);
            throw new RuntimeException("文件上传失败", e);
        }

    }

    public void getObject(String fileName, HttpServletResponse response) {
        InputStream inputStream = null;
        try {
            StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs
                    .builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .build());
            inputStream = minioClient.getObject(GetObjectArgs
                    .builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .build());

            response.setContentType(statObjectResponse.contentType());
            IOUtils.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            log.error("MinIo文件服务异常:{}", fileName);
            throw new RuntimeException("文件读取失败", e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.error("MinIo文件服务异常", e);
            }
        }
    }

    public String getPreUrl(String fileName) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs
                    .builder()
                    .method(Method.GET)
                    .bucket(bucketName)
                    .object(fileName)
                    .build());
        } catch (Exception e) {
            log.error("[MinIo文件服务]", e);
            throw new RuntimeException("文件预览路径获取失败", e);
        }
    }

    public void delObject(String fileName) {
        try {
            minioClient.removeObject(RemoveObjectArgs
                    .builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .build());
        } catch (Exception e) {
            log.error("[MinIo文件服务]文件名称：{}", fileName, e);
            throw new RuntimeException("文件删除失败", e);
        }
    }

    public boolean bucketExists() throws Exception {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    public void makeBucket() throws Exception {
        minioClient.makeBucket(MakeBucketArgs
                .builder()
                .bucket(bucketName)
                .build());
    }
}
